package com.hbnu.handler;
import com.hbnu.message.FileInfo;
import com.hbnu.message.Response;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.handler.codec.serialization.ObjectDecoder;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;


@ChannelHandler.Sharable
public class FileServerHandler extends SimpleChannelInboundHandler<Object> {
    private FileInfo fileInfo;
    private FileChannel fileChannel;
    private RandomAccessFile randomAccessFile;

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object msg) throws Exception {
        if (msg instanceof FileInfo fileInfo) {
            System.out.println("接收的对象: " + fileInfo);
            // 准备写入文件
            this.fileInfo=fileInfo;
            //上传请求
            if(fileInfo.isHasFile()){
                //移除对象编码器，会先将剩余ByteBuf处理完,进行回调，再返回
                initializeFileChannel("rw");
                channelHandlerContext.pipeline().remove(ObjectDecoder.class);
            }
            //下载请求
            else {
                initializeFileChannel("r");
                fileInfo.setHasFile(true);//有内容
                //发送文件描述
                channelHandlerContext.writeAndFlush(fileInfo);
                //直接零拷贝写入
                FileRegion region = new DefaultFileRegion(fileChannel, fileInfo.getStart(), fileInfo.getFileSize());
                channelHandlerContext.writeAndFlush(region).addListener(future -> {
                    if (future.isSuccess()) {
                        System.out.println("文件发送完毕!");
                    } else {
                        System.out.println("文件发送失败!");
                    }
                });
            }
        }
        //文件部分
        else if (msg instanceof ByteBuf buf) {
            // 接收到文件的数据
            int read = fileChannel.write(buf.nioBuffer());
            //读完了
            if(!fileInfo.hasRemaining(read)) {
                System.out.println("文件接收完成！");
                Response response = new Response(true, "上传成功！");
                channelHandlerContext.writeAndFlush(response);
            }
        }
        //其他处理记得传递
        else channelHandlerContext.fireChannelRead(msg);
    }

    private void initializeFileChannel(String mode) throws IOException {
        // 创建目标文件通道
        randomAccessFile = new RandomAccessFile(fileInfo.getsPath(), mode);
        randomAccessFile.seek(fileInfo.getStart());
        fileChannel = randomAccessFile.getChannel();
    }


    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        // 文件发送完成后关闭连接
        if (fileChannel != null) {
            fileChannel.close();
        }
        if (randomAccessFile != null) {
            randomAccessFile.close();
        }
        ctx.close();
        System.out.println("连接关闭");
    }
}
